home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-11-12 | 54.8 KB | 2,636 lines |
- Newsgroups: comp.sources.misc
- From: sjg@zen.void.oz.au (Simon J. Gerraty)
- Subject: v25i047: pdksh - Public Domain Korn Shell, v4, Part01/09
- Message-ID: <csm-v25i047=pdksh.210931@sparky.IMD.Sterling.COM>
- X-Md4-Signature: 49a12c19b06e4666179b8736de09b441
- Date: Wed, 13 Nov 1991 03:10:19 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: sjg@zen.void.oz.au (Simon J. Gerraty)
- Posting-number: Volume 25, Issue 47
- Archive-name: pdksh/part01
- Environment: UNIX
-
- This is the latest version of the PD ksh (pdksh). It is not
- intended to be the ultimate shell but rather a usable ksh work
- alike. For those of us who have to work on multiple systems it
- is nice to have the same user interface on all. Pdksh is not
- 100% compatible with the ksh. Having said that, I use it daily
- beside a real ksh88 and find them virtually indistinguishable.
-
- I only run this shell on sun's and only for interactive use. I
- use it on sun4c, sun3 and sun386 systems. The makefiles are
- probably set up for a sun386 :-).
-
- I am releasing this version of the shell (with the kind
- permission of the previous maintainers and major contributors) to
- ensure that it is available from usenet archive sites. Of
- course it remains in the Public Domain. Equally obviously
- neither myself nor any other contributors make any claims of
- suitability etc. Ie. NO WARRANTY!!!
-
- HISTORY:
-
- This shell was written by Eric Gisin. It is based on Charles
- Forsyth's public domain V7 shell, which he later contributed to
- Minix. John R MacMillan picked up Eric Gisin's version after
- Eric moved on to other projects (see ReadMe.jrm).
-
- Since then there have been many contributors to this shell.
- Most have left their fingerprints within the source and various
- ReadMe.xxx and Changes.xxx files reflect their input.
-
- This version is basically that known as Eric Gisin's version 3.3
- alpha which I obtained indirectly from John R MacMillan who is
- the most recent maintainer. This version has much improved
- emacs-mode command line editing (my main contribution) plus
- enough extra emacs-mode features to make it difficult to
- distinguish from ksh88. Bug fixes from various contributors are
- the only other changes from John MacMillan's version.
-
- I have upped the version number for this release to distinguish
- it from the original 3.3 version. This version is much improved
- despite the small number of new features.
-
- Please see the README for additional information concerning pdksh.
-
- Simon J. Gerraty
- -----------------
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: README . etc sh sh/emacs.c sh/var.c std std/posix std/stdc
- # Wrapped by kent@sparky on Tue Nov 12 20:44:31 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 1 (of 9)."'
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(3792 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- X Public Domain Korn Shell
- X Version 4.1
- X
- XPD KSH:
- X
- XThis is the latest version of the PD ksh (pdksh). It is not
- Xintended to be the ultimate shell but rather a usable ksh work
- Xalike. For those of us who have to work on multiple systems it
- Xis nice to have the same user interface on all. Pdksh is not
- X100% compatible with the ksh. Having said that, I use it daily
- Xbeside a real ksh88 and find them virtually indistinguishable.
- X
- XI only run this shell on sun's and only for interactive use. I
- Xuse it on sun4c, sun3 and sun386 systems. The makefiles are
- Xprobably set up for a sun386 :-).
- X
- XI am releasing this version of the shell (with the kind
- Xpermission of the previous maintainers and major contributors) to
- Xensure that it is available from usenet archive sites. Of
- Xcourse it remains in the Public Domain. Equally obviously
- Xneither myself nor any other contributors make any claims of
- Xsuitability etc. Ie. NO WARRANTY!!!
- X
- XHISTORY:
- X
- XThis shell was written by Eric Gisin. It is based on Charles
- XForsyth's public domain V7 shell, which he later contributed to
- XMinix. John R MacMillan picked up Eric Gisin's version after
- XEric moved on to other projects (see ReadMe.jrm).
- X
- XSince then there have been many contributors to this shell.
- XMost have left their fingerprints within the source and various
- XReadMe.xxx and Changes.xxx files reflect their input.
- X
- XThis version is basically that known as Eric Gisin's version 3.3
- Xalpha which I obtained indirectly from John R MacMillan who is
- Xthe most recent maintainer. This version has much improved
- Xemacs-mode command line editing (my main contribution) plus
- Xenough extra emacs-mode features to make it difficult to
- Xdistinguish from ksh88. Bug fixes from various contributors are
- Xthe only other changes from John MacMillan's version.
- X
- XI have upped the version number for this release to distinguish
- Xit from the original 3.3 version. This version is much improved
- Xdespite the small number of new features.
- X
- XINSTALLATION:
- X
- XReadMe.jrm is John R MacMillan's README file and contains
- Xinformation about the current source arrangement. Please read it.
- X
- XEric Gisin's original ReadMe file can be found in ./sh, it is
- Xsomewhat out of date but retained for history's sake :-) Use
- Xthe instructions in ReadMe.jrm.
- X
- XThe original instructions indicated that a POSIX compliant
- Xenvironment and possibly an ANSI compiler are required. I have
- Xused both gcc and native Sun compilers without problems.
- XActually I use gcc on the sun386 and cc on the others.
- XI do know that a friend's SysVr2 NS3210 system required some
- Xserious modifications to get the shell running. If he ever
- Xsends me the diffs I'll fix the source :-)
- X
- XENVIRONMENT:
- X
- XMy main interest in this shell is for Sun workstations. Every
- Xother UNIX system I use comes with a real ksh. Being a strictly
- XC-shell environment, some improved profile files are in order on
- XSun's.
- X
- XThe etc directory contains a set of useful environment files.
- XThese are the same files I use on several systems (many use a
- Xreal ksh):
- X./etc/profile
- X./etc/sys_config.sh
- X./etc/ksh.kshrc
- X
- XThe first one is obvious. The second, sys_config.sh is sourced
- Xby /etc/profile and several other scripts. It is used to
- Xdetermine the system type so that scripts like profile can be
- Xused on multiple platforms.
- XThe third one is also quite useful, add
- X. /etc/ksh.kshrc
- Xto user's ~/.kshrc to simplify alias management.
- X
- XBUGS:
- X
- XMany folk have contributed to this shell. There are surely
- Xstill plenty of bugs to be found/fixed.
- X
- XFeel free to e-mail fixes to pdksh-bug@zen.void.oz.au
- XPlease use context diffs (ie diff -c, get gnudiff if your
- Xsystem's diff doesn't support -c).
- XI will, if need be, release patches following the C-news style.
- X
- XI hope you find this shell as useful as I do...
- X
- XSimon J. Gerraty <sjg@zen.void.oz.au>
- END_OF_FILE
- if test 3792 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test ! -d 'etc' ; then
- echo shar: Creating directory \"'etc'\"
- mkdir 'etc'
- fi
- if test ! -d 'sh' ; then
- echo shar: Creating directory \"'sh'\"
- mkdir 'sh'
- fi
- if test -f 'sh/emacs.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sh/emacs.c'\"
- else
- echo shar: Extracting \"'sh/emacs.c'\" \(32990 characters\)
- sed "s/^X//" >'sh/emacs.c' <<'END_OF_FILE'
- X/*
- X * Emacs-like command line editing and history
- X *
- X * created by Ron Natalie at BRL
- X * modified by Doug Kingston, Doug Gwyn, and Lou Salkind
- X * adapted to PD ksh by Eric Gisin
- X */
- X
- X#include "config.h"
- X#ifdef EMACS
- X
- X#ifndef lint
- Xstatic char *RCSid = "$Id: emacs.c,v 3.2 89/03/27 15:49:17 egisin Exp $";
- Xstatic char *sccs_id = "@(#)emacs.c 1.5 91/11/09 15:35:13 (sjg)";
- X#endif
- X
- X#include <stddef.h>
- X#include <stdlib.h>
- X#include <string.h>
- X#include <stdio.h>
- X#include <signal.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <dirent.h>
- X#include <unistd.h>
- X#include <fcntl.h>
- X#include <ctype.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include "sh.h"
- X#include "lex.h"
- X#include "tree.h" /* DOTILDE */
- X#include "table.h"
- X#include "expand.h"
- X#include "edit.h"
- X
- X#define PUSH_DELETE 1 /* push all deletes of >1 char */
- X
- Xstatic Area aedit;
- X#define AEDIT &aedit /* area for kill ring and macro defns */
- X
- X#undef CTRL /* _BSD brain damage */
- X#define CTRL(x) ((x) == '?' ? 0x7F : (x) & 0x1F) /* ASCII */
- X#define UNCTRL(x) ((x) == 0x7F ? '?' : (x) | 0x40) /* ASCII */
- X
- X#ifndef S_ISDIR
- X#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
- X#endif
- X
- X#ifndef S_ISREG
- X#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
- X#endif
- X
- X/* values returned by keyboard functions */
- X#define KSTD 0
- X#define KPREF 1 /* ^[, ^X */
- X#define KEOL 2 /* ^M, ^J */
- X#define KINTR 3 /* ^G, ^C */
- X#define KNULL 4
- X
- Xstruct x_ftab {
- X int (*xf_func)();
- X char *xf_name;
- X char xf_db_tab;
- X char xf_db_char;
- X short xf_flags;
- X};
- X
- X#define XF_ALLOC 2
- X#define XF_NOBIND 4
- X
- X#define iscfs(c) (c == ' ' || c == '\t') /* Separator for completion */
- X#define ismfs(c) (!(isalnum(c)|| c == '$')) /* Separator for motion */
- X#define BEL 0x07
- X#define CMASK 0x7F /* 7-bit ASCII character mask */
- X
- Xstatic int x_prefix1 = CTRL('['), x_prefix2 = CTRL('X');
- Xstatic char **x_histp; /* history position */
- Xstatic char **x_nextcmdp; /* for newline-and-next */
- Xstatic char *xmp; /* mark pointer */
- Xstatic int (*x_last_command)();
- X/*static struct x_ftab *x_tab[3][128];*/
- Xstatic struct x_ftab Const *(*x_tab)[128] = NULL; /* key definition */
- Xstatic char *(*x_atab)[128] = NULL; /* macro definitions */
- X#define KILLSIZE 20
- Xstatic char *killstack[KILLSIZE];
- Xstatic int killsp, killtp;
- Xstatic int x_curprefix;
- Xstatic char *macroptr;
- Xstatic int x_maxlen; /* to determine column width */
- X
- Xstatic void x_goto(), x_bs(), x_delete(), x_ins(), x_mapin();
- Xstatic int x_fword(), x_bword(), x_size(), x_size_str();
- Xstatic void x_zotc(), x_zots(), x_push(), x_load_hist();
- Xstatic void compl_command(), compl_dec(), compl_file();
- Xstatic int x_insert(), x_ins_string(), x_del_back();
- Xstatic int x_del_char(), x_del_bword(), x_mv_bword(), x_mv_fword();
- Xstatic int x_del_fword(), x_mv_back(), x_mv_forw(), x_search_char();
- Xstatic int x_newline(), x_end_of_text(), x_abort(), x_error();
- Xstatic int x_beg_hist(), x_end_hist(), x_prev_com(), x_next_com();
- Xstatic int x_search_hist(), x_del_line(), x_mv_end(), x_mv_begin();
- Xstatic int x_draw_line(), x_transpose(), x_meta1(), x_meta2();
- Xstatic int x_kill(), x_yank(), x_meta_yank(), x_literal();
- Xstatic int x_stuffreset(), x_stuff(), x_complete(), x_enumerate();
- Xstatic int x_set_mark(), x_kill_region(), x_xchg_point_mark();
- Xstatic int x_nl_next_com(), x_eot_del();
- Xstatic int x_copy_arg();
- Xstatic int x_noop();
- X#ifdef SILLY
- Xstatic int x_game_of_life();
- X#endif
- Xstatic int x_comp_file(), x_comp_comm();
- Xstatic int x_list_file(), x_list_comm();
- Xstatic int strmatch();
- Xstatic int x_prev_histword(), x_set_arg(), x_fold_case();
- X
- X
- Xstatic struct x_ftab Const x_ftab[] = {
- X {x_insert, "auto-insert", 0, 0, 0 },
- X {x_error, "error", 0, 0, 0 },
- X {x_ins_string, "macro-string", 0, 0, XF_NOBIND|XF_ALLOC},
- X {x_del_back, "delete-char-backward", 0, CTRL('H'), 0 },
- X {x_eot_del, "eot-or-delete", 0, CTRL('D'), 0 },
- X {x_del_bword, "delete-word-backward", 1, CTRL('H'), 0 },
- X {x_mv_bword, "backward-word", 1, 'b', 0 },
- X {x_del_line, "kill-line", 0, 0, 0 },
- X {x_abort, "abort", 0, 0, 0 },
- X {x_noop, "no-op", 0, 0, 0 },
- X/* Do not move the above! */
- X {x_mv_fword, "forward-word", 1, 'f', 0 },
- X {x_del_fword, "delete-word-forward", 1, 'd', 0 },
- X {x_mv_back, "backward-char", 0, CTRL('B'), 0 },
- X {x_mv_forw, "forward-char", 0, CTRL('F'), 0 },
- X {x_search_char, "search-character", 0, CTRL(']'), 0 },
- X {x_newline, "newline", 0, CTRL('M'), 0 },
- X {x_newline, "newline", 0, CTRL('J'), 0 },
- X {x_end_of_text, "eot", 0, CTRL('_'), 0 },
- X {x_abort, "abort", 0, CTRL('G'), 0 },
- X {x_prev_com, "up-history", 0, CTRL('P'), 0},
- X {x_next_com, "down-history", 0, CTRL('N'), 0},
- X {x_search_hist, "search-history", 0, CTRL('R'), 0},
- X {x_beg_hist, "beginning-of-history", 1, '<', 0},
- X {x_end_hist, "end-of-history", 1, '>', 0},
- X {x_mv_end, "end-of-line", 0, CTRL('E'), 0 },
- X {x_mv_begin, "beginning-of-line", 0, CTRL('A'), 0 },
- X {x_draw_line, "redraw", 0, CTRL('L'), 0 },
- X {x_meta1, "prefix-1", 0, CTRL('['), 0 },
- X {x_meta2, "prefix-2", 0, CTRL('X'), 0 },
- X {x_kill, "kill-to-eol", 0, CTRL('K'), 0 },
- X {x_yank, "yank", 0, CTRL('Y'), 0 },
- X {x_meta_yank, "yank-pop", 1, 'y', 0 },
- X {x_literal, "quote", 0, CTRL('^'), 0 },
- X {x_stuffreset, "stuff-reset", 0, 0, 0 },
- X#if defined(BRL) && defined(TIOCSTI)
- X {x_stuff, "stuff", 0, CTRL('T'), 0 },
- X {x_transpose, "transpose-chars", 0, 0, 0 },
- X#else
- X {x_stuff, "stuff", 0, 0, 0 },
- X {x_transpose, "transpose-chars", 0, CTRL('T'), 0 },
- X#endif
- X {x_complete, "complete", 1, CTRL('['), 0 },
- X {x_enumerate, "list", 1, '?', 0 },
- X {x_comp_file, "complete-file", 1, CTRL('X'), 0 },
- X {x_comp_comm, "complete-command", 2, CTRL('['), 0 },
- X {x_list_file, "list-file", 0, 0, 0 },
- X {x_list_comm, "list-command", 2, '?', 0 },
- X {x_nl_next_com, "newline-and-next", 0, CTRL('O'), 0 },
- X {x_set_mark, "set-mark-command", 1, ' ', 0 },
- X {x_kill_region, "kill-region", 0, CTRL('W'), 0 },
- X {x_xchg_point_mark, "exchange-point-and-mark", 2, CTRL('X'), 0 },
- X#if 0
- X {x_copy_arg, "copy-last-arg", 1, '_', 0},
- X#endif
- X#ifdef SILLY
- X {x_game_of_life, "play-game-of-life", 0, 0, 0 },
- X#endif
- X#ifdef DEBUG
- X {x_debug_info, "debug-info", 1, CTRL('H'), 0 },
- X#endif
- X {x_prev_histword, "prev-hist-word", 1, '.', 0 },
- X {x_prev_histword, "prev-hist-word", 1, '_', 0 },
- X {x_set_arg, "", 1, '0', 0 },
- X {x_set_arg, "", 1, '1', 0 },
- X {x_set_arg, "", 1, '2', 0 },
- X {x_set_arg, "", 1, '3', 0 },
- X {x_set_arg, "", 1, '4', 0 },
- X {x_set_arg, "", 1, '5', 0 },
- X {x_set_arg, "", 1, '6', 0 },
- X {x_set_arg, "", 1, '7', 0 },
- X {x_set_arg, "", 1, '8', 0 },
- X {x_set_arg, "", 1, '9', 0 },
- X {x_fold_case, "upcase-word", 1, 'U', 0 },
- X {x_fold_case, "downcase-word", 1, 'L', 0 },
- X {x_fold_case, "capitalize-word", 1, 'C', 0 },
- X {x_fold_case, "upcase-word", 1, 'u', 0 },
- X {x_fold_case, "downcase-word", 1, 'l', 0 },
- X {x_fold_case, "capitalize-word", 1, 'c', 0 },
- X { 0 }
- X};
- X
- X#define xft_insert &x_ftab[0]
- X#define xft_error &x_ftab[1]
- X#define xft_ins_string &x_ftab[2]
- X#define xft_erase &x_ftab[3]
- X#define xft_kill &x_ftab[7]
- X#define xft_werase &x_ftab[5]
- X#define xft_intr &x_ftab[8]
- X#define xft_quit &x_ftab[9]
- X
- Xint
- Xx_emacs(buf, len)
- X char *buf;
- X size_t len;
- X{
- X char c;
- X int i;
- X int (*func)();
- X extern x_insert();
- X
- X xbp = xbuf = buf; xend = buf + len;
- X xlp = xcp = xep = buf;
- X *xcp = 0;
- X xlp_valid = TRUE;
- X xmp = NULL;
- X x_curprefix = 0;
- X macroptr = null;
- X x_histp = histptr + 1;
- X
- X if (x_nextcmdp != NULL) {
- X x_load_hist(x_nextcmdp);
- X x_nextcmdp = NULL;
- X }
- X
- X /* <sjg@sun0> this may not be correct */
- X if ((i = atoi(strval(global("COLUMNS")))) > 0)
- X x_cols = i;
- X else
- X x_cols = 80;
- X x_col = promptlen(prompt);
- X x_adj_ok = 1;
- X x_displen = x_cols - 2 - x_col;
- X x_adj_done = 0;
- X
- X while (1) {
- X x_flush();
- X if (*macroptr) {
- X c = *macroptr++;
- X if (*macroptr == 0)
- X macroptr = null;
- X }
- X else {
- X if ((c = x_getc()) < 0)
- X return i;
- X }
- X
- X if (x_curprefix == -1)
- X func = x_insert;
- X else
- X func = x_tab[x_curprefix][c&CMASK]->xf_func;
- X if (func == NULL)
- X func = x_error;
- X i = c | (x_curprefix << 8);
- X x_curprefix = 0;
- X switch (i = (*func)(i)) {
- X case KSTD:
- X x_last_command = func;
- X case KPREF:
- X case KNULL:
- X break;
- X case KEOL:
- X i = xep - xbuf;
- X x_last_command = 0;
- X return i;
- X case KINTR: /* special case for interrupt */
- X errno = EINTR;
- X return -1;
- X }
- X }
- X}
- X
- Xstatic int
- Xx_insert(c) {
- X char str[2];
- X
- X /*
- X * Should allow tab and control chars.
- X */
- X if (c == 0) {
- X x_putc(BEL);
- X return KSTD;
- X }
- X str[0] = c;
- X str[1] = 0;
- X x_ins(str);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_ins_string(c)
- X{
- X if (*macroptr) {
- X x_putc(BEL);
- X return KSTD;
- X }
- X macroptr = x_atab[c>>8][c & CMASK];
- X return KSTD;
- X}
- X
- Xstatic void
- Xx_ins(cp)
- X char *cp;
- X{
- X int count, i;
- X register int adj = x_adj_done;
- X
- X count = strlen(cp);
- X if (xep+count >= xend) {
- X x_putc(BEL);
- X return;
- X }
- X
- X if (xcp != xep)
- X memmove(xcp+count, xcp, xep - xcp + 1);
- X else
- X xcp[count] = 0;
- X memmove(xcp, cp, count);
- X /*
- X * x_zots() may result in a call to x_adjust()
- X * we want xcp to reflect the new position.
- X */
- X cp = xcp;
- X xcp += count;
- X xep += count;
- X xlp_valid = FALSE;
- X x_lastcp();
- X x_adj_ok = (xcp >= xlp);
- X x_zots(cp);
- X if (adj == x_adj_done) /* has x_adjust() been called? */
- X {
- X /* no */
- X for (cp = xlp; cp > xcp; )
- X x_bs(*--cp);
- X }
- X
- X x_adj_ok = 1;
- X return;
- X}
- X
- Xstatic int
- Xx_del_back(c) {
- X if (xcp == xbuf) {
- X x_putc(BEL);
- X return KSTD;
- X }
- X x_goto(xcp - 1);
- X x_delete(1);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_del_char(c) {
- X if (xcp == xep) {
- X x_putc(BEL);
- X return KSTD;
- X }
- X x_delete(1);
- X return KSTD;
- X}
- X
- Xstatic void
- Xx_delete(nc)
- X int nc;
- X{
- X int i,j;
- X char *cp;
- X
- X if (nc == 0)
- X return;
- X if (xmp != NULL) {
- X if (xcp + nc > xmp)
- X xmp = xcp;
- X else if (xmp > xcp)
- X xmp -= nc;
- X }
- X#ifdef PUSH_DELETE
- X /*
- X * This lets us yank a word we have deleted.
- X */
- X if (nc > 1)
- X x_push(nc);
- X#endif
- X xep -= nc;
- X cp = xcp;
- X j = 0;
- X i = nc;
- X while (i--) {
- X j += x_size(*cp++);
- X }
- X memmove(xcp, xcp+nc, xep - xcp + 1); /* Copies the null */
- X x_adj_ok = 0; /* don't redraw */
- X x_zots(xcp);
- X /*
- X * if we are already filling the line,
- X * there is no need to ' ','\b'.
- X * But if we must, make sure we do the minimum.
- X */
- X if ((i = x_cols - 2 - x_col) > 0)
- X {
- X j = (j < i) ? j : i;
- X i = j;
- X while (i--)
- X x_putc(' ');
- X i = j;
- X while (i--)
- X x_putc('\b');
- X }
- X /*x_goto(xcp);*/
- X x_adj_ok = 1;
- X xlp_valid = FALSE;
- X for (cp = x_lastcp(); cp > xcp; )
- X x_bs(*--cp);
- X
- X return;
- X}
- X
- Xstatic int
- Xx_del_bword(c) {
- X x_delete(x_bword());
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_mv_bword(c) {
- X (void)x_bword();
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_mv_fword(c) {
- X x_goto(xcp + x_fword());
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_del_fword(c) {
- X x_delete(x_fword());
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_bword() {
- X int nc = 0;
- X register char *cp = xcp;
- X
- X if (cp == xbuf) {
- X x_putc(BEL);
- X return 0;
- X }
- X if (x_last_command != x_set_arg)
- X x_arg = 1;
- X while (x_arg--)
- X {
- X while (cp != xbuf && ismfs(cp[-1]))
- X {
- X cp--;
- X nc++;
- X }
- X while (cp != xbuf && !ismfs(cp[-1]))
- X {
- X cp--;
- X nc++;
- X }
- X }
- X x_goto(cp);
- X return nc;
- X}
- X
- Xstatic int
- Xx_fword() {
- X int nc = 0;
- X register char *cp = xcp;
- X
- X if (cp == xep) {
- X x_putc(BEL);
- X return 0;
- X }
- X if (x_last_command != x_set_arg)
- X x_arg = 1;
- X while (x_arg--)
- X {
- X while (cp != xep && !ismfs(*cp))
- X {
- X cp++;
- X nc++;
- X }
- X while (cp != xep && ismfs(*cp))
- X {
- X cp++;
- X nc++;
- X }
- X }
- X return nc;
- X}
- X
- Xstatic void
- Xx_goto(cp)
- X register char *cp;
- X{
- X if (cp < xbp || cp >= (xbp + x_displen))
- X {
- X /* we are heading off screen */
- X xcp = cp;
- X x_adjust();
- X }
- X else
- X {
- X if (cp < xcp) /* move back */
- X {
- X while (cp < xcp)
- X x_bs(*--xcp);
- X }
- X else
- X {
- X if (cp > xcp) /* move forward */
- X {
- X while (cp > xcp)
- X x_zotc(*xcp++);
- X }
- X }
- X }
- X}
- X
- Xstatic void
- Xx_bs(c) {
- X register i;
- X i = x_size(c);
- X while (i--)
- X x_putc('\b');
- X}
- X
- Xstatic int
- Xx_size_str(cp)
- X register char *cp;
- X{
- X register size = 0;
- X while (*cp)
- X size += x_size(*cp++);
- X return size;
- X}
- X
- Xstatic int
- Xx_size(c) {
- X if (c=='\t')
- X return 4; /* Kludge, tabs are always four spaces. */
- X if (c < ' ' || c == 0x7F) /* ASCII control char */
- X return 2;
- X return 1;
- X}
- X
- Xstatic void
- Xx_zots(str)
- X register char *str;
- X{
- X register int adj = x_adj_done;
- X
- X x_lastcp();
- X while (*str && str < xlp && adj == x_adj_done)
- X x_zotc(*str++);
- X}
- X
- Xstatic void
- Xx_zotc(c)
- X int c;
- X{
- X if (c == '\t') {
- X /* Kludge, tabs are always four spaces. */
- X x_puts(" ");
- X } else if (c < ' ' || c == 0x7F) { /* ASCII */
- X x_putc('^');
- X x_putc(UNCTRL(c));
- X } else
- X x_putc(c);
- X}
- X
- Xstatic int
- Xx_mv_back(c) {
- X if (xcp == xbuf) {
- X x_putc(BEL);
- X return KSTD;
- X }
- X x_goto(xcp-1);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_mv_forw(c) {
- X if (xcp == xep) {
- X x_putc(BEL);
- X return KSTD;
- X }
- X x_goto(xcp+1);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_search_char(c)
- X int c;
- X{
- X char *cp;
- X
- X *xep = '\0';
- X if ((c = x_getc()) < 0 ||
- X /* we search forward, I don't know what Korn does */
- X (cp = (xcp == xep) ? NULL : strchr(xcp+1, c)) == NULL &&
- X (cp = strchr(xbuf, c)) == NULL) {
- X x_putc(BEL);
- X return KSTD;
- X }
- X x_goto(cp);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_newline(c) {
- X x_putc('\n');
- X x_flush();
- X *xep++ = '\n';
- X return KEOL;
- X}
- X
- Xstatic int
- Xx_end_of_text(c) {
- X#if 0
- X x_store_hist();
- X#endif
- X return KEOL;
- X}
- X
- Xstatic int x_beg_hist(c) {x_load_hist(history); return KSTD;}
- X
- Xstatic int x_end_hist(c) {x_load_hist(histptr); return KSTD;}
- X
- Xstatic int x_prev_com(c) {x_load_hist(x_histp-1); return KSTD;}
- X
- Xstatic int x_next_com(c) {x_load_hist(x_histp+1); return KSTD;}
- X
- Xstatic void
- Xx_load_hist(hp)
- X register char **hp;
- X{
- X int oldsize;
- X
- X if (hp < history || hp > histptr) {
- X x_putc(BEL);
- X return;
- X }
- X x_histp = hp;
- X oldsize = x_size_str(xbuf);
- X (void)strcpy(xbuf, *hp);
- X xbp = xbuf;
- X xep = xcp = xbuf + strlen(*hp);
- X xlp_valid = FALSE;
- X if (xep > x_lastcp())
- X x_goto(xep);
- X else
- X x_redraw(oldsize);
- X}
- X
- Xstatic int
- Xx_nl_next_com(c)
- Xint c;
- X{
- X x_nextcmdp = x_histp + 1;
- X return (x_newline(c));
- X}
- X
- Xstatic int
- Xx_eot_del(c)
- Xint c;
- X{
- X if (xep == xbuf)
- X return (x_end_of_text(c));
- X else
- X return (x_del_char(c));
- X}
- X
- Xstatic int x_search(), x_match();
- X
- X/* reverse incremental history search */
- Xstatic int
- Xx_search_hist(c)
- X int c;
- X{
- X int offset = -1; /* offset of match in xbuf, else -1 */
- X char pat [256+1]; /* pattern buffer */
- X register char *p = pat;
- X int (*func)();
- X
- X *p = 0;
- X while (1) {
- X if (offset < 0) {
- X x_puts("\nI-search: ");
- X x_zots(pat);
- X }
- X x_flush();
- X if ((c = x_getc()) < 0)
- X return KSTD;
- X func = x_tab[0][c&CMASK]->xf_func;
- X if (c == CTRL('['))
- X break;
- X else if (func == x_search_hist)
- X offset = x_search(pat, offset);
- X else if (func == x_del_back)
- X continue; /* todo */
- X else if (func == x_insert) {
- X /* add char to pattern */
- X *p++ = c, *p = 0;
- X if (offset >= 0) {
- X /* already have partial match */
- X offset = x_match(xbuf, pat);
- X if (offset >= 0) {
- X x_goto(xbuf + offset + (p - pat) - (*pat == '^'));
- X continue;
- X }
- X }
- X offset = x_search(pat, offset);
- X } else { /* other command */
- X static char push[2];
- X push[0] = c;
- X macroptr = push; /* push command */
- X break;
- X }
- X }
- X if (offset < 0)
- X x_redraw(-1);
- X return KSTD;
- X}
- X
- X/* search backward from current line */
- Xstatic int
- Xx_search(pat, offset)
- X char *pat;
- X int offset;
- X{
- X register char **hp;
- X int i;
- X
- X for (hp = x_histp; --hp >= history; ) {
- X i = x_match(*hp, pat);
- X if (i >= 0) {
- X if (offset < 0)
- X x_putc('\n');
- X x_load_hist(hp);
- X x_goto(xbuf + i + strlen(pat) - (*pat == '^'));
- X return i;
- X }
- X }
- X x_putc(BEL);
- X x_histp = histptr;
- X return -1;
- X}
- X
- X/* return position of first match of pattern in string, else -1 */
- Xstatic int
- Xx_match(str, pat)
- X char *str, *pat;
- X{
- X if (*pat == '^') {
- X return (strncmp(str, pat+1, strlen(pat+1)) == 0) ? 0 : -1;
- X } else {
- X char *q = strstr(str, pat);
- X return (q == NULL) ? -1 : q - str;
- X }
- X}
- X
- Xstatic int
- Xx_del_line(c) {
- X int i, j;
- X
- X *xep = 0;
- X i = xep- xbuf;
- X j = x_size_str(xbuf);
- X xcp = xbuf;
- X x_push(i);
- X xlp = xbp = xep = xbuf;
- X xlp_valid = TRUE;
- X *xcp = 0;
- X xmp = NULL;
- X x_redraw(j);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_mv_end(c) {
- X x_goto(xep);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_mv_begin(c) {
- X x_goto(xbuf);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_draw_line(c)
- X{
- X x_redraw(-1);
- X return KSTD;
- X
- X}
- X
- Xvoid
- Xx_redraw(limit)
- X int limit;
- X{
- X int i, j;
- X char *cp;
- X
- X x_adj_ok = 0;
- X if (limit == -1)
- X x_putc('\n');
- X else
- X x_putc('\r');
- X x_flush();
- X if (xbp == xbuf)
- X {
- X pprompt(prompt);
- X x_col = promptlen(prompt);
- X }
- X x_displen = x_cols - 2 - x_col;
- X xlp_valid = FALSE;
- X cp = x_lastcp();
- X x_zots(xbp);
- X if (xbp != xbuf || xep > xlp)
- X limit = x_cols;
- X if (limit >= 0)
- X {
- X if (xep > xlp)
- X i = 0; /* we fill the line */
- X else
- X i = limit - (xlp - xbp);
- X
- X for (j = 0; j < i && x_col < (x_cols - 2); j++)
- X x_putc(' ');
- X i = ' ';
- X if (xep > xlp) /* more off screen */
- X {
- X if (xbp > xbuf)
- X i = '*';
- X else
- X i = '>';
- X }
- X else
- X if (xbp > xbuf)
- X i = '<';
- X x_putc(i);
- X j++;
- X while (j--)
- X x_putc('\b');
- X }
- X for (cp = xlp; cp > xcp; )
- X x_bs(*--cp);
- X x_adj_ok = 1;
- X _D_(x_flush();)
- X return;
- X}
- X
- Xstatic int
- Xx_transpose(c) {
- X char tmp;
- X if (xcp == xbuf) {
- X x_putc(BEL);
- X return KSTD;
- X } else if (xcp == xep) {
- X if (xcp - xbuf == 1) {
- X x_putc(BEL);
- X return KSTD;
- X }
- X x_bs(xcp[-1]);
- X x_bs(xcp[-2]);
- X x_zotc(xcp[-1]);
- X x_zotc(xcp[-2]);
- X tmp = xcp[-1];
- X xcp[-1] = xcp[-2];
- X xcp[-2] = tmp;
- X } else {
- X x_bs(xcp[-1]);
- X x_zotc(xcp[0]);
- X x_zotc(xcp[-1]);
- X tmp = xcp[-1];
- X xcp[-1] = xcp[0];
- X xcp[0] = tmp;
- X x_bs(xcp[0]);
- X }
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_literal(c) {
- X x_curprefix = -1;
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_meta1(c) {
- X x_curprefix = 1;
- X return KPREF;
- X}
- X
- Xstatic int
- Xx_meta2(c) {
- X x_curprefix = 2;
- X return KPREF;
- X}
- X
- Xstatic int
- Xx_kill(c) {
- X int i;
- X
- X i = xep - xcp;
- X xlp = xcp;
- X xlp_valid = TRUE;
- X x_push(i);
- X x_delete(i);
- X return KSTD;
- X}
- X
- Xstatic void
- Xx_push(nchars) {
- X char *cp;
- X cp = alloc((size_t)(nchars+1), AEDIT);
- X memmove(cp, xcp, nchars);
- X cp[nchars] = 0;
- X if (killstack[killsp])
- X afree((Void *)killstack[killsp], AEDIT);
- X killstack[killsp] = cp;
- X killsp = (killsp + 1) % KILLSIZE;
- X}
- X
- Xstatic int
- Xx_yank(c) {
- X if (killsp == 0)
- X killtp = KILLSIZE;
- X else
- X killtp = killsp;
- X killtp --;
- X if (killstack[killtp] == 0) {
- X x_puts("\nnothing to yank");
- X x_redraw(-1);
- X return KSTD;
- X }
- X xmp = xcp;
- X x_ins(killstack[killtp]);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_meta_yank(c) {
- X int len;
- X if (x_last_command != x_yank && x_last_command != x_meta_yank) {
- X x_puts("\nyank something first");
- X x_redraw(-1);
- X return KSTD;
- X }
- X len = strlen(killstack[killtp]);
- X x_goto(xcp - len);
- X x_delete(len);
- X do {
- X if (killtp == 0)
- X killtp = KILLSIZE - 1;
- X else
- X killtp--;
- X } while (killstack[killtp] == 0);
- X x_ins(killstack[killtp]);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_abort(c) {
- X /* x_zotc(c); */
- X xlp = xep = xcp = xbp = xbuf;
- X xlp_valid = TRUE;
- X *xcp = 0;
- X return KINTR;
- X}
- X
- Xstatic int
- Xx_error(c) {
- X x_putc(BEL);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_stuffreset(c)
- X{
- X#ifdef TIOCSTI
- X (void)x_stuff(c);
- X return KINTR;
- X#else
- X x_zotc(c);
- X xlp = xcp = xep = xbp = xbuf;
- X xlp_valid = TRUE;
- X *xcp = 0;
- X x_redraw(-1);
- X return KSTD;
- X#endif
- X}
- X
- Xstatic int
- Xx_stuff(c)
- X{
- X#if 0 || defined TIOCSTI
- X char ch = c;
- X bool_t savmode = x_mode(FALSE);
- X
- X (void)ioctl(ttyfd, TIOCSTI, &ch);
- X (void)x_mode(savmode);
- X x_redraw(-1);
- X#endif
- X return KSTD;
- X}
- X
- Xstatic void
- Xx_mapin(cp)
- X char *cp;
- X{
- X char *op;
- X
- X op = cp;
- X while (*cp) {
- X /* XXX -- should handle \^ escape? */
- X if (*cp == '^') {
- X cp++;
- X if (*cp >= '?') /* includes '?'; ASCII */
- X *op++ = CTRL(*cp);
- X else {
- X *op++ = '^';
- X cp--;
- X }
- X } else
- X *op++ = *cp;
- X cp++;
- X }
- X *op = 0;
- X}
- X
- Xstatic char *
- Xx_mapout(c)
- X int c;
- X{
- X static char buf[8];
- X register char *p = buf;
- X
- X if (c < ' ' || c == 0x7F) { /* ASCII */
- X *p++ = '^';
- X *p++ = (c == 0x7F) ? '?' : (c | 0x40);
- X } else
- X *p++ = c;
- X *p = 0;
- X return buf;
- X}
- X
- Xstatic void
- Xx_print(prefix, key)
- X int prefix, key;
- X{
- X if (prefix == 1)
- X shellf("%s", x_mapout(x_prefix1));
- X if (prefix == 2)
- X shellf("%s", x_mapout(x_prefix2));
- X shellf("%s = ", x_mapout(key));
- X if (x_tab[prefix][key]->xf_func != x_ins_string)
- X shellf("%s\n", x_tab[prefix][key]->xf_name);
- X else
- X shellf("'%s'\n", x_atab[prefix][key]);
- X}
- X
- Xvoid
- Xx_bind(a1, a2, macro)
- X char *a1, *a2;
- X int macro; /* bind -m */
- X{
- X struct x_ftab Const *fp;
- X int prefix, key;
- X char *sp = NULL;
- X
- X if (x_tab == NULL)
- X errorf("cannot bind, not a tty\n");
- X
- X if (a1 == NULL) {
- X for (prefix = 0; prefix < 3; prefix++)
- X for (key = 0; key < 0x80; key++) {
- X fp = x_tab[prefix][key];
- X if (fp == NULL ||
- X fp->xf_func == x_insert || fp->xf_func == x_error)
- X continue;
- X x_print(prefix, key);
- X }
- X return;
- X }
- X
- X x_mapin(a1);
- X prefix = key = 0;
- X for (;; a1++) {
- X key = *a1;
- X if (x_tab[prefix][key]->xf_func == x_meta1)
- X prefix = 1;
- X else
- X if (x_tab[prefix][key]->xf_func == x_meta2)
- X prefix = 2;
- X else
- X break;
- X }
- X
- X if (a2 == NULL) {
- X x_print(prefix, key);
- X return;
- X }
- X
- X if (*a2 == 0)
- X fp = xft_insert;
- X else if (!macro) {
- X for (fp = x_ftab; fp->xf_func; fp++)
- X if (strcmp(fp->xf_name, a2) == 0)
- X break;
- X if (fp->xf_func == NULL || (fp->xf_flags & XF_NOBIND))
- X errorf("%s: no such function\n", a2);
- X if (fp->xf_func == x_meta1)
- X x_prefix1 = key;
- X if (fp->xf_func == x_meta2)
- X x_prefix2 = key;
- X } else {
- X fp = xft_ins_string;
- X x_mapin(a2);
- X sp = strsave(a2, AEDIT);
- X }
- X
- X if ((x_tab[prefix][key]->xf_flags & XF_ALLOC) && x_atab[prefix][key])
- X afree((Void *)x_atab[prefix][key], AEDIT);
- X x_tab[prefix][key] = fp;
- X x_atab[prefix][key] = sp;
- X}
- X
- Xvoid
- Xx_init_emacs()
- X{
- X register int i, j;
- X struct x_ftab Const *fp;
- X
- X ainit(AEDIT);
- X
- X x_tab = (struct x_ftab ***) alloc(sizeofN(*x_tab, 3), AEDIT);
- X for (j = 0; j < 128; j++)
- X x_tab[0][j] = xft_insert;
- X for (i = 1; i < 3; i++)
- X for (j = 0; j < 128; j++)
- X x_tab[i][j] = xft_error;
- X for (fp = x_ftab; fp->xf_func; fp++)
- X if (fp->xf_db_char || fp->xf_db_tab)
- X x_tab[fp->xf_db_tab][fp->xf_db_char] = fp;
- X
- X x_atab = (char ***) alloc(sizeofN(*x_atab, 3), AEDIT);
- X for (i = 1; i < 3; i++)
- X for (j = 0; j < 128; j++)
- X x_atab[i][j] = NULL;
- X}
- X
- Xvoid
- Xx_emacs_keys(erase, kill, werase, intr, quit)
- X int erase, kill, werase, intr, quit;
- X{
- X x_tab[0][erase] = xft_erase;
- X x_tab[0][kill] = xft_kill;
- X x_tab[0][werase] = xft_werase;
- X x_tab[0][intr] = xft_intr;
- X x_tab[0][quit] = xft_quit;
- X}
- X
- Xstatic int
- Xx_set_mark(c) {
- X xmp = xcp;
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_kill_region(c) {
- X int rsize;
- X char *xr;
- X
- X if (xmp == NULL) {
- X x_putc(BEL);
- X return KSTD;
- X }
- X if (xmp > xcp) {
- X rsize = xmp - xcp;
- X xr = xcp;
- X } else {
- X rsize = xcp - xmp;
- X xr = xmp;
- X }
- X x_goto(xr);
- X x_push(rsize);
- X x_delete(rsize);
- X xmp = xr;
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_xchg_point_mark(c) {
- X char *tmp;
- X
- X if (xmp == NULL) {
- X x_putc(BEL);
- X return KSTD;
- X }
- X tmp = xmp;
- X xmp = xcp;
- X x_goto( tmp );
- X return KSTD;
- X}
- X
- X#if 0
- Xstatic int
- Xx_copy_arg(c) {
- X char *last;
- X if ((last = strval(local("_"))) && *last)
- X x_ins(last);
- X return KSTD;
- X}
- X#endif
- X
- Xstatic int
- Xx_noop(c) {
- X return KNULL;
- X}
- X
- X#ifdef SILLY
- Xstatic int
- Xx_game_of_life(c) {
- X char newbuf [256+1];
- X register char *ip, *op;
- X int i, len;
- X
- X i = xep - xbuf;
- X *xep = 0;
- X len = x_size_str(xbuf);
- X xcp = xbp = xbuf;
- X memmove(newbuf+1, xbuf, i);
- X newbuf[0] = 'A';
- X newbuf[i] = 'A';
- X for (ip = newbuf+1, op = xbuf; --i >= 0; ip++, op++) {
- X /* Empty space */
- X if (*ip < '@' || *ip == '_' || *ip == 0x7F) {
- X /* Two adults, make whoopee */
- X if (ip[-1] < '_' && ip[1] < '_') {
- X /* Make kid look like parents. */
- X *op = '`' + ((ip[-1] + ip[1])/2)%32;
- X if (*op == 0x7F) /* Birth defect */
- X *op = '`';
- X }
- X else
- X *op = ' '; /* nothing happens */
- X continue;
- X }
- X /* Child */
- X if (*ip > '`') {
- X /* All alone, dies */
- X if (ip[-1] == ' ' && ip[1] == ' ')
- X *op = ' ';
- X else /* Gets older */
- X *op = *ip-'`'+'@';
- X continue;
- X }
- X /* Adult */
- X /* Overcrowded, dies */
- X if (ip[-1] >= '@' && ip[1] >= '@') {
- X *op = ' ';
- X continue;
- X }
- X *op = *ip;
- X }
- X *op = 0;
- X x_redraw(len);
- X return KSTD;
- X}
- X#endif
- X
- X/*
- X * File/command name completion routines
- X */
- X
- X/* type: 0 for list, 1 for completion */
- X
- Xstatic XPtrV words;
- X
- Xstatic void
- Xadd_stash(dirnam, name)
- X char *dirnam; /* directory name, if file */
- X char *name;
- X{
- X char *cp;
- X register int type = 0; /* '*' if executable, '/' if directory, else 0 */
- X register int len = strlen(name);
- X
- X /* determine file type */
- X if (dirnam) {
- X struct stat statb;
- X char *buf = alloc((size_t)(strlen(dirnam)+len+2), ATEMP);
- X
- X if (strcmp(dirnam, ".") == 0)
- X *buf = '\0';
- X else if (strcmp(dirnam, "/") == 0)
- X (void)strcpy(buf, "/");
- X else
- X (void)strcat(strcpy(buf, dirnam), "/");
- X (void)strcat(buf, name);
- X if (stat(buf, &statb)==0)
- X if (S_ISDIR(statb.st_mode))
- X type = '/';
- X else if (S_ISREG(statb.st_mode) && access(buf, 01)==0)
- X type = '*';
- X if (type)
- X ++len;
- X afree((Void *)buf, ATEMP);
- X }
- X
- X if (len > x_maxlen)
- X x_maxlen = len;
- X
- X /* stash name for later sorting */
- X cp = alloc((size_t)(len+1), ATEMP);
- X (void)strcpy(cp = alloc((size_t)(len+1), ATEMP), name);
- X if (dirnam && type) { /* append file type indicator */
- X cp[len-1] = type;
- X cp[len] = '\0';
- X }
- X XPput(words, cp);
- X}
- X
- Xstatic void
- Xlist_stash()
- X{
- X register char **array, **record;
- X int items = 0, tabstop, loc, nrows, jump, offset;
- X
- X items = XPsize(words);
- X array = (char**) XPptrv(words);
- X if (items == 0)
- X return;
- X qsortp(XPptrv(words), (size_t)XPsize(words), xstrcmp);
- X
- X /* print names */
- X x_maxlen = (x_maxlen/8 + 1) * 8; /* column width */
- X nrows = (items-1) / (x_cols/x_maxlen) + 1;
- X for (offset = 0; offset < nrows; ++offset) {
- X tabstop = loc = 0;
- X x_putc('\n');
- X for (jump = 0; offset+jump < items; jump += nrows) {
- X if (jump)
- X while (loc < tabstop) {
- X x_putc('\t');
- X loc = (loc/8 + 1) * 8;
- X }
- X record = array + (offset + jump);
- X x_puts(*record);
- X loc += strlen(*record);
- X tabstop += x_maxlen; /* next tab stop */
- X afree((Void *)*record, ATEMP);
- X }
- X }
- X
- X afree((Void*)array, ATEMP);
- X x_redraw(-1);
- X}
- X
- Xstatic int
- Xx_comp_comm(c) {
- X compl_command(1);
- X return KSTD;
- X}
- Xstatic int
- Xx_list_comm(c) {
- X compl_command(0);
- X return KSTD;
- X}
- Xstatic int
- Xx_complete(c) {
- X compl_dec(1);
- X return KSTD;
- X}
- Xstatic int
- Xx_enumerate(c) {
- X compl_dec(0);
- X return KSTD;
- X}
- Xstatic int
- Xx_comp_file(c) {
- X compl_file(1);
- X return KSTD;
- X}
- Xstatic int
- Xx_list_file(c) {
- X compl_file(0);
- X return KSTD;
- X}
- X
- Xstatic void
- Xcompl_dec(type)
- X{
- X char *cp;
- X cp = xcp;
- X
- X while (cp != xbuf && !iscfs(*cp))
- X cp--;
- X if (cp == xbuf && strchr(cp, '/') == NULL)
- X compl_command(type);
- X else
- X compl_file(type);
- X}
- X
- Xstatic void
- Xcompl_file(type)
- X{
- X char *str;
- X register char *cp, *xp;
- X char *lastp;
- X char *dirnam;
- X char buf [256+1];
- X char bug [256+1];
- X DIR *dirp;
- X struct dirent *dp;
- X long loc = -1;
- X int len;
- X int multi = 0;
- X
- X str = xcp;
- X cp = buf;
- X xp = str;
- X while (xp != xbuf) {
- X --xp;
- X if (iscfs(*xp)) {
- X xp++;
- X break;
- X }
- X }
- X if (digit(*xp) && (xp[1] == '<' || xp[1] == '>'))
- X xp++;
- X while (*xp == '<' || *xp == '>')
- X xp++;
- X if (type)
- X while (*xcp && !iscfs(*xcp))
- X x_zotc(*xcp++);
- X else {
- X x_maxlen = 0;
- X XPinit(words, 16);
- X }
- X while (*xp && !iscfs(*xp))
- X *cp++ = *xp++;
- X
- X *cp = 0;
- X strcpy(buf, cp = substitute(buf, DOTILDE));
- X afree((Void*)cp, ATEMP);
- X lastp = strrchr(buf, '/');
- X if (lastp)
- X *lastp = 0;
- X
- X dirnam = (lastp == NULL) ? "." : (lastp == buf) ? "/" : buf;
- X dirp = opendir(dirnam);
- X if (dirp == NULL) {
- X x_putc(BEL);
- X return;
- X }
- X
- X if (lastp == NULL)
- X lastp = buf;
- X else
- X lastp++;
- X len = strlen(lastp);
- X
- X while ((dp = readdir(dirp)) != NULL) {
- X cp = dp->d_name;
- X if (cp[0] == '.' &&
- X (cp[1] == '\0' || cp[1] == '.' && cp[2] == '\0'))
- X continue; /* always ignore . and .. */
- X if (strncmp(lastp, cp, len) == 0)
- X if (type) {
- X if (loc == -1) {
- X (void)strcpy(bug, cp);
- X loc = strlen(cp);
- X } else {
- X multi = 1;
- X loc = strmatch(bug, cp);
- X bug[loc] = 0;
- X }
- X } else
- X add_stash(dirnam, cp);
- X }
- X (void)closedir(dirp);
- X
- X if (type) {
- X if (loc <= 0) {
- X x_putc(BEL);
- X return;
- X }
- X cp = bug + len;
- X x_ins(cp);
- X if (!multi) {
- X struct stat statb;
- X if (lastp == buf)
- X buf[0] = 0;
- X else if (lastp == buf + 1) {
- X buf[1] = 0;
- X buf[0] = '/';
- X } else
- X (void)strcat(buf, "/");
- X (void)strcat(buf, bug);
- X if (stat(buf, &statb) == 0 && S_ISDIR(statb.st_mode))
- X x_ins("/");
- X else
- X x_ins(" ");
- X }
- X } else
- X list_stash();
- X}
- X
- Xstatic void
- Xcompl_command(type)
- X{
- X register struct tbl *tp;
- X char *str;
- X char buf [256+1];
- X char bug [256+1];
- X char *xp;
- X char *cp;
- X int len;
- X int multi;
- X int loc;
- X
- X str = xcp;
- X cp = buf;
- X xp = str;
- X while (xp != xbuf) {
- X --xp;
- X if (iscfs(*xp)) {
- X xp++;
- X break;
- X }
- X }
- X if (type)
- X while (*xcp && !iscfs(*xcp))
- X x_zotc(*xcp++);
- X else {
- X x_maxlen = 0;
- X XPinit(words, 16);
- X }
- X while (*xp && !iscfs(*xp))
- X *cp++ = *xp++;
- X *cp = 0;
- X
- X len = strlen(buf);
- X loc = -1;
- X multi = 0;
- X
- X for (twalk(&commands); (tp = tnext()) != NULL; ) {
- X int klen;
- X
- X if (!(tp->flag&ISSET))
- X continue;
- X klen = strlen(tp->name);
- X if (klen < len)
- X continue;
- X if (strncmp(buf, tp->name, len) ==0)
- X if (type) {
- X if (loc == -1) {
- X (void)strcpy(bug, tp->name);
- X loc = klen;
- X } else {
- X multi = 1;
- X loc = strmatch(bug, tp->name);
- X bug[loc] = 0;
- X }
- X } else
- X add_stash((char *)0, tp->name);
- X }
- X
- X if (type) {
- X if (loc <= 0) {
- X x_putc(BEL);
- X return;
- X }
- X cp = bug + len;
- X x_ins(cp);
- X if (!multi)
- X x_ins(" ");
- X } else
- X list_stash();
- X}
- X
- Xstatic int
- Xstrmatch(s1, s2)
- X register char *s1, *s2;
- X{
- X register char *p;
- X
- X for (p = s1; *p == *s2++ && *p != 0; p++)
- X ;
- X return p - s1;
- X}
- X
- X
- X
- X/* NAME:
- X * x_set_arg - set an arg value for next function
- X *
- X * DESCRIPTION:
- X * This is a simple implementation of M-[0-9].
- X *
- X * RETURN VALUE:
- X * KSTD
- X */
- X
- Xstatic int
- Xx_set_arg(c)
- X int c;
- X{
- X if ((x_arg = (c &= CMASK) - '0') < 0 || x_arg > 9)
- X {
- X x_arg = 1;
- X x_putc(BEL);
- X }
- X return KSTD;
- X}
- X
- X
- X/* NAME:
- X * x_prev_histword - recover word from prev command
- X *
- X * DESCRIPTION:
- X * This function recovers the last word from the previous
- X * command and inserts it into the current edit line. If a
- X * numeric arg is supplied then the n'th word from the
- X * start of the previous command is used.
- X *
- X * Bound to M-.
- X *
- X * RETURN VALUE:
- X * KSTD
- X */
- X
- Xstatic int
- Xx_prev_histword()
- X{
- X register char *rcp;
- X char *cp;
- X char **hp;
- X
- X hp = x_histp-1;
- X if (hp < history || hp > histptr)
- X {
- X x_putc(BEL);
- X return;
- X }
- X cp = *hp;
- X if (x_last_command != x_set_arg)
- X {
- X rcp = &cp[strlen(cp) - 1];
- X /*
- X * ignore white-space after the last word
- X */
- X while (rcp > cp && iscfs(*rcp))
- X rcp--;
- X while (rcp > cp && !iscfs(*rcp))
- X rcp--;
- X if (iscfs(*rcp))
- X rcp++;
- X x_ins(rcp);
- X }
- X else
- X {
- X int c;
- X
- X rcp = cp;
- X /*
- X * ignore white-space at start of line
- X */
- X while (*rcp && iscfs(*rcp))
- X rcp++;
- X while (x_arg-- > 1)
- X {
- X while (*rcp && !iscfs(*rcp))
- X rcp++;
- X while (*rcp && iscfs(*rcp))
- X rcp++;
- X }
- X cp = rcp;
- X while (*rcp && !iscfs(*rcp))
- X rcp++;
- X c = *rcp;
- X *rcp = '\0';
- X x_ins(cp);
- X *rcp = c;
- X }
- X return KSTD;
- X}
- X
- X/* NAME:
- X * x_fold_case - convert word to UPPER/lower case
- X *
- X * DESCRIPTION:
- X * This function is used to implement M-u,M-l and M-c
- X * to upper case, lower case or Capitalize words.
- X *
- X * RETURN VALUE:
- X * None
- X */
- X
- Xstatic int
- Xx_fold_case(c)
- X int c;
- X{
- X register char *cp = xcp;
- X
- X if (cp == xep)
- X {
- X x_putc(BEL);
- X return 0;
- X }
- X c &= 0137; /* strip prefixes and case */
- X if (x_last_command != x_set_arg)
- X x_arg = 1;
- X while (x_arg--)
- X {
- X /*
- X * fisrt skip over any white-space
- X */
- X while (cp != xep && ismfs(*cp))
- X {
- X cp++;
- X }
- X /*
- X * do the first char on its own since it may be
- X * a different action than for the rest.
- X */
- X if (cp != xep)
- X {
- X if (c == 'L') /* M-l */
- X {
- X if (isupper(*cp))
- X *cp = tolower(*cp);
- X }
- X else /* M-u or M-c */
- X {
- X if (islower(*cp))
- X *cp = toupper(*cp);
- X }
- X cp++;
- X }
- X /*
- X * now for the rest of the word
- X */
- X while (cp != xep && !ismfs(*cp))
- X {
- X if (c == 'U') /* M-u */
- X {
- X if (islower(*cp))
- X *cp = toupper(*cp);
- X }
- X else /* M-l or M-c */
- X {
- X if (isupper(*cp))
- X *cp = tolower(*cp);
- X }
- X cp++;
- X }
- X }
- X x_goto(cp);
- X return 0;
- X}
- X
- X/* NAME:
- X * x_lastcp - last visible char
- X *
- X * SYNOPSIS:
- X * x_lastcp()
- X *
- X * DESCRIPTION:
- X * This function returns a pointer to that char in the
- X * edit buffer that will be the last displayed on the
- X * screen. The sequence:
- X *
- X * for (cp = x_lastcp(); cp > xcp; cp)
- X * x_bs(*--cp);
- X *
- X * Will position the cursor correctly on the screen.
- X *
- X * RETURN VALUE:
- X * cp or NULL
- X */
- X
- Xchar *
- Xx_lastcp()
- X{
- X register char *rcp;
- X register int i;
- X
- X if (!xlp_valid)
- X {
- X for (i = 0, rcp = xbp; rcp < xep && i < x_displen; rcp++)
- X i += x_size(*rcp);
- X xlp = rcp;
- X }
- X xlp_valid = TRUE;
- X return (xlp);
- X}
- X
- X#endif /* EDIT */
- X
- END_OF_FILE
- if test 32990 -ne `wc -c <'sh/emacs.c'`; then
- echo shar: \"'sh/emacs.c'\" unpacked with wrong size!
- fi
- # end of 'sh/emacs.c'
- fi
- if test -f 'sh/var.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sh/var.c'\"
- else
- echo shar: Extracting \"'sh/var.c'\" \(11520 characters\)
- sed "s/^X//" >'sh/var.c' <<'END_OF_FILE'
- X#ifndef lint
- Xstatic char *RCSid = "$Id: var.c,v 3.2 89/03/27 15:52:21 egisin Exp $";
- Xstatic char *sccs_id = "@(#)var.c 1.3 91/11/09 15:35:17 (sjg)";
- X#endif
- X
- X#include <stddef.h>
- X#include <string.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include <time.h>
- X#include "sh.h"
- X#include "table.h"
- X#include "expand.h"
- X
- X/*
- X * Variables
- X *
- X * WARNING: unreadable code, needs a rewrite
- X *
- X * if (flag&INTEGER), val.i contains integer value, and type contains base.
- X * otherwise, (val.s + type) contains string value.
- X * if (flag&EXPORT), val.s contains "name=value" for E-Z exporting.
- X */
- Xchar null [] = "";
- Xstatic struct tbl vtemp;
- Xstatic void getspec(), setspec();
- Xstatic void export ARGS((struct tbl *, char *val));
- Xstatic int special ARGS ((char *name));
- X
- X/*
- X * create a new block for function calls and simple commands
- X * assume caller has allocated and set up e.loc
- X */
- Xvoid
- Xnewblock()
- X{
- X register struct block *l = e.loc;
- X static char *empty[] = {""};
- X
- X ainit(&l->area);
- X l->argc = 0;
- X l->argv = empty;
- X l->exit = l->error = NULL;
- X tinit(&l->vars, &l->area);
- X tinit(&l->funs, &l->area);
- X}
- X
- X/*
- X * pop a block handling special variables
- X */
- Xvoid
- Xpopblock()
- X{
- X register struct block *l = e.loc;
- X register struct tbl *vp, **vpp = l->vars.tbls;
- X register int i;
- X
- X e.loc = l->next; /* pop block */
- X for (i = l->vars.size; --i >= 0; )
- X if ((vp = *vpp++) != NULL && (vp->flag&SPECIAL))
- X setspec(global(vp->name));
- X afreeall(&l->area);
- X}
- X
- X/*
- X * Search for variable, if not found create globally.
- X */
- Xstruct tbl *
- Xglobal(n)
- X register char *n;
- X{
- X register struct block *l = e.loc;
- X register struct tbl *vp;
- X register int c;
- X unsigned h = hash(n);
- X
- X c = n[0];
- X if (digit(c)) {
- X vp = &vtemp;
- X lastarea = ATEMP;
- X vp->flag = (DEFINED|RDONLY);
- X vp->type = 0;
- X *vp->name = c; /* should strncpy */
- X for (c = 0; digit(*n) && c < 1000; n++)
- X c = c*10 + *n-'0';
- X if (c <= l->argc)
- X setstr(vp, l->argv[c]);
- X return vp;
- X } else
- X if (!letter(c)) {
- X vp = &vtemp;
- X lastarea = ATEMP;
- X vp->flag = (DEFINED|RDONLY);
- X vp->type = 0;
- X *vp->name = c;
- X if (n[1] != '\0')
- X return vp;
- X vp->flag |= ISSET|INTEGER;
- X switch (c) {
- X case '$':
- X vp->val.i = kshpid;
- X break;
- X case '!':
- X vp->val.i = async;
- X break;
- X case '?':
- X vp->val.i = exstat;
- X break;
- X case '#':
- X vp->val.i = l->argc;
- X break;
- X case '-':
- X vp->flag &= ~ INTEGER;
- X vp->val.s = getoptions();
- X break;
- X default:
- X vp->flag &= ~(ISSET|INTEGER);
- X }
- X return vp;
- X }
- X for (l = e.loc; l != NULL; l = l->next) {
- X vp = tsearch(&l->vars, n, h);
- X lastarea = &l->area;
- X if (vp != NULL)
- X return vp;
- X if (l->next == NULL)
- X break;
- X }
- X vp = tenter(&l->vars, n, h);
- X vp->flag |= DEFINED;
- X if (special(n))
- X vp->flag |= SPECIAL;
- X return vp;
- X}
- X
- X/*
- X * Search for local variable, if not found create locally.
- X */
- Xstruct tbl *
- Xlocal(n)
- X register char *n;
- X{
- X register struct block *l = e.loc;
- X register struct tbl *vp;
- X unsigned h = hash(n);
- X
- X if (!letter(*n)) {
- X vp = &vtemp;
- X lastarea = ATEMP;
- X vp->flag = (DEFINED|RDONLY);
- X vp->type = 0;
- X return vp;
- X }
- X vp = tenter(&l->vars, n, h);
- X lastarea = &l->area;
- X vp->flag |= DEFINED;
- X if (special(n))
- X vp->flag |= SPECIAL;
- X return vp;
- X}
- X
- X/* get variable string value */
- Xchar *
- Xstrval(vp)
- X register struct tbl *vp;
- X{
- X register char *s;
- X static char strbuf[40];
- X
- X if ((vp->flag&SPECIAL))
- X getspec(vp);
- X if (!(vp->flag&ISSET))
- X return null; /* special to dollar() */
- X if (!(vp->flag&INTEGER)) /* string source */
- X s = vp->val.s + vp->type;
- X else { /* integer source */
- X register unsigned long n;
- X register int base;
- X
- X s = strbuf + sizeof(strbuf);
- X n = (vp->val.i < 0) ? -vp->val.i : vp->val.i;
- X base = (vp->type == 0) ? 10 : vp->type;
- X
- X *--s = '\0';
- X do {
- X *--s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[n%base];
- X n /= base;
- X } while (n != 0);
- X /* todo: should we output base# ? */
- X if (vp->val.i < 0)
- X *--s = '-';
- X }
- X return s;
- X}
- X
- X/* get variable integer value */
- Xlong
- Xintval(vp)
- X register struct tbl *vp;
- X{
- X register struct tbl *vq;
- X
- X if ((vp->flag&SPECIAL))
- X getspec(vp);
- X if ((vp->flag&INTEGER))
- X return vp->val.i;
- X vq = &vtemp;
- X vq->flag = (INTEGER);
- X vq->type = 0;
- X if (strint(vq, vp) == NULL)
- X errorf("%s: bad number\n", vp->val.s);
- X return vq->val.i;
- X}
- X
- X/* set variable to string value */
- Xvoid
- Xsetstr(vq, s)
- X register struct tbl *vq;
- X char *s;
- X{
- X if (!(vq->flag&INTEGER)) { /* string dest */
- X if ((vq->flag&ALLOC))
- X afree((Void*)vq->val.s, lastarea);
- X vq->flag &= ~ (ISSET|ALLOC);
- X vq->type = 0;
- X if ((vq->flag&EXPORT))
- X export(vq, s);
- X else
- X vq->val.s = strsave(s, lastarea);
- X vq->flag |= ALLOC;
- X } else { /* integer dest */
- X register struct tbl *vp = &vtemp;
- X vp->flag = (DEFINED|ISSET);
- X vp->type = 0;
- X vp->val.s = s;
- X if (strint(vq, vp) == NULL)
- X errorf("%s: bad number\n", s);
- X }
- X vq->flag |= ISSET;
- X if ((vq->flag&SPECIAL))
- X setspec(vq);
- X}
- X
- X/* convert variable to integer variable */
- Xstruct tbl *
- Xstrint(vq, vp)
- X register struct tbl *vq, *vp;
- X{
- X register char *s = vp->val.s + vp->type;
- X register int c;
- X int base, neg = 0;
- X
- X vq->flag |= INTEGER;
- X if (!(vp->flag&ISSET) || (s == NULL && !(vp->flag&INTEGER))) {
- X vq->flag &= ~ ISSET;
- X return NULL;
- X }
- X if ((vp->flag&INTEGER)) {
- X vq->val.i = vp->val.i;
- X return vq;
- X }
- X vq->val.i = 0;
- X base = 10;
- X for (c = *s++; c ; c = *s++)
- X if (c == '-') {
- X neg++;
- X } else if (c == '#') {
- X base = vq->type = vq->val.i;
- X vq->val.i = 0;
- X } else if (letnum(c)) {
- X if ('0' <= c && c <= '9')
- X c -= '0';
- X else if ('a' <= c && c <= 'z') /* fuck EBCDIC */
- X c -= 'a'-10;
- X else if ('A' <= c && c <= 'Z')
- X c -= 'A'-10;
- X if (c < 0 || c >= base) {
- X vq->flag &= ~ ISSET;
- X return NULL;
- X }
- X vq->val.i = (vq->val.i*base) + c;
- X } else
- X break;
- X if (neg)
- X vq->val.i = -vq->val.i;
- X if (vq->type < 2 || vq->type > 36)
- X vq->type = 0; /* default base (10) */
- X return vq;
- X}
- X
- X/* set variable to integer */
- Xvoid
- Xsetint(vq, n)
- X register struct tbl *vq;
- X long n;
- X{
- X if (!(vq->flag&INTEGER)) {
- X register struct tbl *vp = &vtemp;
- X vp->flag = (ISSET|INTEGER);
- X vp->type = 0;
- X vp->val.i = n;
- X setstr(vq, strval(vp)); /* ? */
- X } else
- X vq->val.i = n;
- X vq->flag |= ISSET;
- X if ((vq->flag&SPECIAL))
- X setspec(vq);
- X}
- X
- X/* set variable from enviroment */
- Ximport(thing)
- X char *thing;
- X{
- X register struct tbl *vp;
- X register char *val;
- X
- X val = strchr(thing, '=');
- X if (val == NULL)
- X return 0;
- X *val = '\0';
- X vp = local(thing);
- X *val++ = '=';
- X vp->flag |= DEFINED|ISSET|EXPORT;
- X vp->val.s = thing;
- X vp->type = val - thing;
- X if ((vp->flag&SPECIAL))
- X setspec(vp);
- X return 1;
- X}
- X
- X/*
- X * make vp->val.s be "name=value" for quick exporting.
- X */
- Xstatic void
- Xexport(vp, val)
- X register struct tbl *vp;
- X char *val;
- X{
- X register char *cp, *xp;
- X char *op = (vp->flag&ALLOC) ? vp->val.s : NULL;
- X
- X xp = (char*)alloc(strlen(vp->name) + strlen(val) + 2, lastarea);
- X vp->flag |= ALLOC;
- X vp->val.s = xp;
- X for (cp = vp->name; (*xp = *cp++) != '\0'; xp++)
- X ;
- X *xp++ = '=';
- X vp->type = xp - vp->val.s; /* offset to value */
- X for (cp = val; (*xp++ = *cp++) != '\0'; )
- X ;
- X if (op != NULL)
- X afree((Void*)op, lastarea);
- X}
- X
- X/*
- X * lookup variable (according to (set&LOCAL)),
- X * set its attributes (INTEGER, RDONLY, EXPORT, TRACE),
- X * and optionally set its value if an assignment.
- X */
- Xstruct tbl *
- Xtypeset(var, set, clr)
- X register char *var;
- X int clr, set;
- X{
- X register struct tbl *vp;
- X register char *val;
- X
- X /* check for valid variable name, search for value */
- X val = var;
- X if (!letter(*val))
- X return NULL;
- X for (val++; *val != '\0'; val++)
- X if (*val == '=')
- X break;
- X else if (letnum(*val))
- X ;
- X else
- X return NULL;
- X if (*val == '=')
- X *val = '\0';
- X else
- X val = NULL;
- X vp = (set&LOCAL) ? local(var) : global(var);
- X set &= ~ LOCAL;
- X if (val != NULL)
- X *val++ = '=';
- X
- X if (!(vp->flag&ISSET))
- X vp->flag = vp->flag & ~clr | set;
- X else
- X if (!(vp->flag&INTEGER) && (set&INTEGER)) {
- X /* string to integer */
- X vtemp.flag = (ISSET);
- X vtemp.type = 0;
- X vtemp.val.s = vp->val.s + vp->type;
- X if ((vp->flag&ALLOC))
- X afree((Void*)vp->val.s, lastarea); /* dangerous, used later */
- X vp->flag &= ~ ALLOC;
- X vp->flag |= INTEGER;
- X vp->type = 0;
- X if (val == NULL && strint(vp, &vtemp) == NULL) {
- X vp->flag &= ~ ISSET;
- X errorf("%s: bad number\n", vtemp.val.s);
- X }
- X } else
- X if ((clr&INTEGER) && (vp->flag&INTEGER)) {
- X /* integer to string */
- X vtemp.val.s = strval(vp);
- X vp->flag &= ~ INTEGER;
- X setstr(vp, vtemp.val.s);
- X }
- X
- X vp->flag = vp->flag & ~clr | set;
- X
- X if (val != NULL) {
- X if ((vp->flag&RDONLY))
- X errorf("cannot set readonly %s\n", var);
- X if ((vp->flag&INTEGER))
- X /* setstr should be able to handle this */
- X (void)evaluate(var);
- X else
- X setstr(vp, val);
- X }
- X
- X if ((vp->flag&EXPORT) && !(vp->flag&INTEGER) && vp->type == 0)
- X export(vp, (vp->flag&ISSET) ? vp->val.s : null);
- X
- X return vp;
- X}
- X
- Xvoid
- Xunset(vp)
- X register struct tbl *vp;
- X{
- X if ((vp->flag&ALLOC))
- X afree((Void*)vp->val.s, lastarea);
- X vp->flag &= SPECIAL; /* Should ``unspecial'' some vars */
- X}
- X
- Xint
- Xisassign(s)
- X register char *s;
- X{
- X if (!letter(*s))
- X return (0);
- X for (s++; *s != '='; s++)
- X if (*s == 0 || !letnum(*s))
- X return (0);
- X return (1);
- X}
- X
- X/*
- X * Make the exported environment from the exported names in the dictionary.
- X */
- Xchar **
- Xmakenv()
- X{
- X struct block *l = e.loc;
- X XPtrV env;
- X register struct tbl *vp, **vpp;
- X register int i;
- X
- X XPinit(env, 64);
- X for (l = e.loc; l != NULL; l = l->next)
- X for (vpp = l->vars.tbls, i = l->vars.size; --i >= 0; )
- X if ((vp = *vpp++) != NULL
- X && (vp->flag&(ISSET|EXPORT)) == (ISSET|EXPORT)) {
- X register struct block *l2;
- X register struct tbl *vp2;
- X unsigned h = hash(vp->name);
- X
- X lastarea = &l->area;
- X
- X /* unexport any redefined instances */
- X for (l2 = l->next; l2 != NULL; l2 = l2->next) {
- X vp2 = tsearch(&l2->vars, vp->name, h);
- X if (vp2 != NULL)
- X vp2->flag &= ~ EXPORT;
- X }
- X if ((vp->flag&INTEGER)) {
- X /* integer to string */
- X char *val;
- X val = strval(vp);
- X vp->flag &= ~ INTEGER;
- X setstr(vp, val);
- X }
- X XPput(env, vp->val.s);
- X }
- X XPput(env, NULL);
- X return (char **) XPclose(env);
- X}
- X
- X/*
- X * handle special variables with side effects - PATH, SECONDS.
- X */
- X
- Xstatic int
- Xspecial(name)
- X register char * name;
- X{
- X if (strcmp("PATH", name) == 0)
- X return V_PATH;
- X if (strcmp("IFS", name) == 0)
- X return V_IFS;
- X if (strcmp("SECONDS", name) == 0)
- X return V_SECONDS;
- X if (strcmp("OPTIND", name) == 0)
- X return V_OPTIND;
- X if (strcmp("MAIL", name) == 0)
- X return V_MAIL;
- X if (strcmp("MAILPATH", name) == 0)
- X return V_MAILPATH;
- X if (strcmp("RANDOM", name) == 0)
- X return V_RANDOM;
- X return V_NONE;
- X}
- X
- Xextern time_t time();
- Xstatic time_t seconds; /* time SECONDS last set */
- Xextern int rand();
- Xextern void srand();
- X
- Xstatic void
- Xgetspec(vp)
- X register struct tbl *vp;
- X{
- X switch (special(vp->name)) {
- X case V_SECONDS:
- X vp->flag &= ~ SPECIAL;
- X setint(vp, time((time_t *)0) - seconds);
- X vp->flag |= SPECIAL;
- X break;
- X case V_RANDOM:
- X vp->flag &= ~ SPECIAL;
- X setint(vp, (rand() & 0x7fff));
- X vp->flag |= SPECIAL;
- X break;
- X }
- X}
- X
- Xstatic void
- Xsetspec(vp)
- X register struct tbl *vp;
- X{
- X extern void mbset(), mpset();
- X
- X switch (special(vp->name)) {
- X case V_PATH:
- X path = strval(vp);
- X flushcom(1); /* clear tracked aliases */
- X break;
- X case V_IFS:
- X setctypes(strval(vp), C_IFS);
- X break;
- X case V_SECONDS:
- X seconds = time((time_t *)0);
- X break;
- X case V_OPTIND:
- X if (intval(vp) == 1)
- X resetopts();
- X break;
- X case V_MAIL:
- X mbset(strval(vp));
- X break;
- X case V_MAILPATH:
- X mpset(strval(vp));
- X break;
- X case V_RANDOM:
- X vp->flag &= ~ SPECIAL;
- X srand((unsigned int)intval(vp));
- X vp->flag |= SPECIAL;
- X break;
- X }
- X}
- X
- END_OF_FILE
- if test 11520 -ne `wc -c <'sh/var.c'`; then
- echo shar: \"'sh/var.c'\" unpacked with wrong size!
- fi
- # end of 'sh/var.c'
- fi
- if test ! -d 'std' ; then
- echo shar: Creating directory \"'std'\"
- mkdir 'std'
- fi
- if test ! -d 'std/posix' ; then
- echo shar: Creating directory \"'std/posix'\"
- mkdir 'std/posix'
- fi
- if test ! -d 'std/stdc' ; then
- echo shar: Creating directory \"'std/stdc'\"
- mkdir 'std/stdc'
- fi
- echo shar: End of archive 1 \(of 9\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 9 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-